import io
import json
import os
import tempfile
import time
from pathlib import Path
import zipfile
from wsgiref.util import FileWrapper

from django.contrib.auth.decorators import login_required, permission_required
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.http import FileResponse, HttpResponse
from django.utils.encoding import escape_uri_path
from rest_framework.generics import GenericAPIView
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.views import TokenObtainPairView
from .serializers import *
from django_filters.rest_framework import DjangoFilterBackend
from .utils import PageNum
from .filters import *
from django.contrib.auth.models import User, Group


# 管理员登录
class LoginView(APIView):
    def post(self, request, *args, **kwargs):
        data = json.loads(request.body)
        try:
            user = User.objects.get(username=data.get('username'), password=data.get('password'))
            d = RefreshToken.for_user(user)
            return Response({"token": str(d.access_token)})
        except Exception as e:
            return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)


class UserInfoView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        try:
            return Response({'data': UserSerializer(request.user).data}, status.HTTP_200_OK)
        except:
            return Response({}, status.HTTP_400_BAD_REQUEST)


# 问卷
class SurveyView(viewsets.ModelViewSet):
    serializer_class = SurveySerializer
    permission_classes = [IsAdminUser]
    queryset = Survey.objects.all().order_by('-id')
    filter_backends = (DjangoFilterBackend,)
    filter_class = SurveyFilter
    pagination_class = PageNum

    def create(self, request, *args, **kwargs):
        data = request.data.copy()
        data['user'] = request.user.id
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    @action(detail=True, methods=['GET'])
    def get_submit(self, request, *args, **kwargs):
        id = kwargs['pk']
        data = Survey.objects.get(id=id).submitsurvey_set.order_by('-status')
        s = SubmitSurveySerializer(data, many=True)
        return Response(s.data, status=status.HTTP_201_CREATED)


# 提交问卷
class SubmitView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        data = request.data.copy()
        data['user'] = request.user.id
        data['survey'] = kwargs['pk']
        data['status'] = "未审核"
        num = SubmitSurvey.objects.filter(user_id=request.user.id, survey_id=kwargs['pk']).count()
        survey = Survey.objects.get(id=kwargs['pk'])
        if not survey.is_active:
            return Response({'message': '该问卷已停止填写'}, status=status.HTTP_400_BAD_REQUEST)

        max_num = json.loads(survey.setting)['num']
        if max_num != 0 and num >= max_num:
            return Response({'message': '该问卷只允许填写一次'}, status=status.HTTP_400_BAD_REQUEST)

        serializer = SubmitSurveySerializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)


class CheckView(APIView):
    permission_classes = [IsAdminUser]

    def post(self, request, *args, **kwargs):
        data = json.loads(request.body)
        if not data.get('status', None) or not data.get('id', None):
            return Response({'message': '缺少参数'}, status=status.HTTP_400_BAD_REQUEST)

        s = SubmitSurvey.objects.get(id=data['id'])
        if s.status != '未审核':
            return Response({'message': '不可再次审核'}, status=status.HTTP_400_BAD_REQUEST)
        s.status = data['status']
        s.save()
        return Response({'message': '审核成功'})


# 图片上传
class ImageView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        try:
            i = Image.objects.get(md5=request.data.get('md5'))
            s = ImageSerializer(i, context={
                'request': request
            })
            return Response(s.data)
        except:
            s = ImageSerializer(data=request.data, context={
                'request': request
            })
            s.is_valid()
            s.save()
            return Response(s.data)


# 获取地区
class AreaView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        data = []
        with open("json/Allarea.json", "r", encoding="utf8") as fp:
            data = json.loads(fp.read())
            fp.close()
        return Response(data)


# 文件上传
class FileView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        try:
            i = File.objects.get(md5=request.GET.get('md5'))
            s = FileSerializer(i, context={
                'request': request
            })
            return Response(s.data)
        except:
            all = os.listdir("upload/file/")
            list = []
            for i in all:
                if request.GET.get('md5') in i:
                    list.append(i)
            return Response({'data': list})

    def post(self, request, *args, **kwargs):
        with open('upload/file/' + request.data.get('md5') + '-' + request.data.get('num'), 'wb+') as destination:
            for chunk in request.data.get('file').chunks():
                destination.write(chunk)
        destination.close()
        return Response({'code': 200, 'message': '上传成功'})


# 文件上传成功
class FileSuccessView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        my_file = Path('upload/file/' + request.data.get('name'))
        if my_file.exists():
            name = str(int(round(time.time() * 1000000))) + '_' + request.data.get('name')
        else:
            name = request.data.get('name')
        # 先创建文件数据
        try:
            s = File.objects.get(md5=request.data.get('md5'))
            s = FileSerializer(s, context={
                'request': request
            })
            return Response(s.data)
        except:
            s = File.objects.create(file='file/' + name, md5=request.data.get('md5'))
            s = FileSerializer(s, context={
                'request': request
            })

        with open('upload/file/' + name, 'wb+') as target_file:
            for i in range(0, int(request.data.get('num', 0))):
                source_file = open('upload/file/' + request.data.get('md5') + '-' + str(i), 'rb')
                target_file.write(source_file.read())
                source_file.close()
                my_file = Path('upload/file/' + request.data.get('md5') + '-' + str(i))
                if my_file.exists():
                    os.remove('upload/file/' + request.data.get('md5') + '-' + str(i))
        target_file.close()
        return Response(s.data)


# 获取用户提交的问卷
class MySubmitSurveyView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        paginator = Paginator(
            SubmitSurvey.objects.filter(user_id=request.user.id).order_by('-create_time'),
            request.GET.get('limit'))
        page = request.GET.get('page')
        try:
            contacts = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            contacts = paginator.page(1)
        except EmptyPage:
            contacts = paginator.page(paginator.num_pages)
        data = SubmitSurveySerializer(contacts, many=True).data
        return Response({'results': data, 'next': contacts.has_next()})


# 获取用户可以填的问卷
class MySurveyView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        data = SurveySerializer(Survey.objects.filter(is_active=True).order_by('-id'), many=True).data
        return Response(data)


# 获取问卷详情
class SurveyDetailView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        s = SurveySerializer(Survey.objects.get(id=kwargs.get('pk')))

        return Response(s.data)


# 用户管理
class UserView(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    permission_classes = [IsAdminUser]
    queryset = User.objects.all().order_by('-is_staff', 'id')
    filter_backends = (DjangoFilterBackend,)
    pagination_class = PageNum

    def create(self, request, *args, **kwargs):
        request.data['is_superuser'] = request.data['is_staff']
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        if request.data['is_staff'] == '1':
            User.objects.get(id=serializer.data.get('id')).groups.add(Group.objects.get(id=1))
        else:
            User.objects.get(id=serializer.data.get('id')).groups.add(Group.objects.get(id=2))
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)


# 已填写的问卷
class SubmitSurveyView(viewsets.ModelViewSet):
    permission_classes = [IsAuthenticated]
    queryset = SubmitSurvey.objects.all().order_by('-id')
    filter_backends = (DjangoFilterBackend,)
    pagination_class = PageNum
    serializer_class = SubmitSurveySerializer

    def create(self, request, *args, **kwargs):
        return Response({})

    def update(self, request, *args, **kwargs):
        s = self.get_object()

        if s.status != '审核不通过':
            return Response({'message': '不可修改'}, status=status.HTTP_400_BAD_REQUEST)
        if not request.data.get('text', None):
            return Response({'message': '缺少参数'})
        s.text = request.data.get('text')
        s.status = '未审核'
        s.save()
        return Response({'message': '修改成功'})


# 注册
class RegisterView(APIView):

    def post(self, request, *args, **kwargs):
        data = json.loads(request.body)
        data['is_staff'] = 0
        data['is_superuser'] = data['is_staff']
        serializer = UserSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        User.objects.get(id=serializer.data.get('id')).groups.add(Group.objects.get(id=2))
        return Response(serializer.data, status=status.HTTP_201_CREATED)


class PackView(APIView):

    def post(self, request, *args, **kwargs):
        s = io.BytesIO()
        data = request.POST.get('list', None)
        if not data:
            return Response({'message': '缺少必要参数'})
        data = json.loads(data)
        if len(data) == 0:
            return Response({'message': '缺少必要参数'})

        temp = tempfile.TemporaryDirectory()
        name = str(int(round(time.time() * 1000000)))
        z = zipfile.ZipFile(s, 'w')
        list = SubmitSurvey.objects.filter(id__in=data, survey_id=kwargs.get('pk'))
        for i in list:
            a = json.loads(i.text)
            img_num = 1
            file_num = 1
            for j in a:
                if j['type'] == '6':
                    for k in j['answer']:
                        file = Image.objects.get(id=k['id'])
                        type = os.path.splitext('upload/' + str(file.file))[1]
                        z.write(r'upload/' + str(file.file),
                                arcname=str(i.id) + '_image_' + str(i.user) + '_' + str(img_num) + type)
                        img_num = img_num + 1

                if j['type'] == '8':
                    for k in j['answer']:
                        file = File.objects.get(id=k['id'])
                        type = os.path.splitext('upload/' + str(file.file))[1]
                        z.write(r'upload/' + str(file.file),
                                arcname=str(i.id) + '_file_' + str(i.user) + '_' + str(file_num) + type)
                        file_num = file_num + 1
        z.close()
        s.seek(0)
        wrapper = FileWrapper(s)
        response = HttpResponse(wrapper, content_type='application/zip')
        response['Content-Disposition'] = 'attachment; filename=' + name + '.zip'
        return response
